(function() {
	module('Burning rope tests Tests');

	test('Setup OK', function() {
		ok(true);
	});

	test('Test initial state', function() {
		var view = new TestView();
		var controller = new RopeController(view);

		controller.startup();

		var expected = [ {
			top : -1,
			bottom : -1,
			burned : false
		}, {
			top : -1,
			bottom : -1,
			burned : false
		} ];

		deepEqual(view.ropesState, expected);
		ok(!view.onWinCalled);
		ok(!view.onStaleCalled);

	});

	test('Test reset', function() {
		var view = new TestView();
		var controller = new RopeController(view);

		controller.startup();
		controller.onSetFire(0, 'top');
		controller.updateTime(5);
		controller.reset();

		var expected = [ {
			top : -1,
			bottom : -1,
			burned : false
		}, {
			top : -1,
			bottom : -1,
			burned : false
		} ];

		deepEqual(view.ropesState, expected);
	});

	test('Test onSetFire on rope time 0', function() {
		var view = new TestView();
		var controller = new RopeController(view);

		controller.startup();

		var ropeIndex = 0;
		controller.onSetFire(ropeIndex, 'top');

		var expected = [ {
			top : 0,
			bottom : -1,
			burned : false
		}, {
			top : -1,
			bottom : -1,
			burned : false
		} ];

		deepEqual(view.ropesState, expected);
	});

	test('Test onSetFire on 2 ropes time 0', function() {
		var view = new TestView();
		var controller = new RopeController(view);

		controller.startup();

		var ropeIndex = 0;
		controller.onSetFire(ropeIndex, 'top');
		controller.onSetFire(ropeIndex, 'bottom');

		ropeIndex = 1;
		controller.onSetFire(ropeIndex, 'top');

		var expected = [ {
			top : 0,
			bottom : 0,
			burned : false
		}, {
			top : 0,
			bottom : -1,
			burned : false
		} ];

		deepEqual(view.ropesState, expected);
	});

	test('Test ein progress', function() {
		var view = new TestView();
		var controller = new RopeController(view);

		controller.startup();

		var ropeIndex = 0;
		controller.onSetFire(ropeIndex, 'top');
		controller.onSetFire(ropeIndex, 'bottom');

		controller.updateTime(5);

		ok(!view.onWinCalled);
		ok(!view.onStaleCalled);
	});

	test('Test expected state on time 15', function() {
		var view = new TestView();
		var controller = new RopeController(view);

		controller.startup();

		var ropeIndex = 0;
		controller.onSetFire(ropeIndex, 'top');
		controller.onSetFire(ropeIndex, 'bottom');

		controller.updateTime(15);

		// second rope unmodified
		var ropeState2 = view.ropesState[1];
		ok((ropeState2.bottom === ropeState2.top) && ropeState2.bottom < 0);

		// first rope top and bottom must intersect at time 15
		ok(view.ropesState[0].top + view.ropesState[0].bottom === 1);
	});

	test('Test rope full burned on time 30', function() {
		var view = new TestView();
		var controller = new RopeController(view);

		controller.startup();

		var ropeIndex = 0;
		controller.onSetFire(ropeIndex, 'top');

		controller.updateTime(30);

		ok(view.ropesState[0].top === 1);
	});

	test('Test solution (time 45)', function() {
		var view = new TestView();
		var controller = new RopeController(view);

		controller.startup();
		controller.onSetFire(0, 'top');
		controller.onSetFire(0, 'bottom');

		controller.updateTime(15);
		var secondRopeIndex = 1;
		controller.onSetFire(secondRopeIndex, 'bottom');

		controller.updateTime(30);
		ok(view.ropesState[secondRopeIndex].bottom < 1);

		controller.updateTime(45);

		var expected = [ {
			top : 1,
			bottom : 1,
			burned : true
		}, {
			top : -1,
			bottom : 1,
			burned : true
		} ];

		deepEqual(view.ropesState, expected);
		ok(view.onSolvedCalled);
	});

	test('Test solution with tolerance (time 45+d)', function() {
		var view = new TestView();
		var controller = new RopeController(view);

		controller.startup();
		controller.onSetFire(0, 'top');
		controller.onSetFire(0, 'bottom');

		var humanDelay = controller.tolerance * 0.9;
		controller.updateTime(15 + humanDelay);
		var secondRopeIndex = 1;
		controller.onSetFire(secondRopeIndex, 'bottom');

		controller.updateTime(30);
		ok(view.ropesState[secondRopeIndex].bottom < 1);

		controller.updateTime(45);
		controller.updateTime(45 + controller.tolerance);

		ok(view.onSolvedCalled);
	});

	test('Test stale at 15', function() {
		var view = new TestView();
		var controller = new RopeController(view);

		controller.startup();
		controller.onSetFire(0, 'top');
		controller.onSetFire(0, 'bottom');
		controller.onSetFire(1, 'top');
		controller.onSetFire(1, 'bottom');

		controller.updateTime(15);

		ok(view.onStaleCalled);
		ok(!view.overTime);
	});

	test('Test stale at 30', function() {
		var view = new TestView();
		var controller = new RopeController(view);

		controller.startup();
		controller.onSetFire(0, 'top');
		controller.onSetFire(1, 'bottom');

		controller.updateTime(30);

		ok(view.onStaleCalled);
		ok(!view.overTime);
	});

	test('Test stale after 45', function() {
		var view = new TestView();
		var controller = new RopeController(view);

		controller.startup();
		controller.onSetFire(0, 'top');

		controller.updateTime(30);
		controller.onSetFire(1, 'bottom');

		controller.updateTime(45 + controller.tolerance);

		ok(view.onStaleCalled);
		ok(view.overTime);
	});

	function TestView() {
		this.ropes = null;
	}

	TestView.prototype.init = function(controller) {
		this.onSolvedCalled = false;
		this.onStaleCalled = false;
	};

	TestView.prototype.update = function(ropesState) {
		this.ropesState = ropesState;
	};

	TestView.prototype.onSolved = function() {
		this.onSolvedCalled = true;
	};

	TestView.prototype.onStale = function(overTime) {
		this.onStaleCalled = true;
		this.overTime = overTime;
	};
}());